package com.threepure.penpipe.redo;

import android.graphics.Bitmap;
import android.util.Log;

import com.threepure.penpipe.util.BitmapUtil;
import com.threepure.penpipe.util.Config;

import java.util.ArrayList;
import java.util.List;

/**
 * @author ThreePure
 * @date 2021/11/17 9:25
 * @description: 撤销/重做 操作工具类
 * @since 1.8
 */
public class StepOperator {

    private static final String TAG = "TP_StepOperator";

    /**
     * 允许的最大缓存步骤数
     */
    private static final int CAPACITY = 12;

    /**
     * 保存每一步绘制的bitmap
     */
    private List<Bitmap> bitmapList = null;

    /**
     * 当前可以进行撤销的位置，当前位置并不是传统意义上上堆、队列上的头指针和尾指针，而是已有的bitmap中区分redo/undo的指针。撤销一步并不是把这个bitmap删除了
     * 而是将这个指针移动一位，只有在内存溢出以及超过最大的缓存步数后才会进行删除。
     */
    private int currentIndex;

    private boolean isUndo = false;

    /**
     * 最大缓存空间大小
     */
    private int cacheMemory;

    public StepOperator() {
        if (bitmapList == null) {
            bitmapList = new ArrayList<>();
        }
        currentIndex = -1;
        //返回Java虚拟机将尝试使用的最大内存量
        int maxMemory = (int) Runtime.getRuntime().maxMemory();
        cacheMemory = maxMemory / 3;
    }

    /**
     * @description: 重置这个回退队列，释放缓存的bitmap以及清空存储bitmap的集合
     * @Param: []
     * @Return: void
     */
    public void reset() {

        if (bitmapList != null) {
            for (Bitmap bitmap : bitmapList) {
                bitmap.recycle();
            }
            bitmapList.clear();
        }
        currentIndex = -1;
    }

    /**
     * @description:  内存是否足够 够的话返回true，否则返回false
     * @Param: []
     * @Return: boolean
     */
    private boolean isMemoryEnable() {

        int bitmapCache = 0;
        for (Bitmap bitmap : bitmapList) {
            bitmapCache += bitmap.getRowBytes() * bitmap.getHeight();
        }
        if (bitmapCache > cacheMemory) {
            return false;
        }
        return true;
    }

    /**
     * @description:  缓存当前绘制的Bitmap
     * @Param: [android.graphics.Bitmap]
     * @Return: void
     */
    public void addBitmap(Bitmap bitmap) {

        if (bitmapList == null) {
            return;
        }

        try {
            // 内存不够且最少存储了一个bitmap（要是一个都没有那也不可能导致内存不足）。那么就要将最开始的哪个删除即可。
            if (!isMemoryEnable() && bitmapList.size() > 1) {
                bitmapList.get(1).recycle();
                //删除第一笔（0的位置有空的占位图）    删除此列表中指定位置的元素（可选操作）。将任何后续元素向左移动（从其索引中减去一个）
                bitmapList.remove(1);
            }
            // 表示已经经过了
            if (currentIndex != -1 && isUndo) {
                for (int i = currentIndex + 1; i < bitmapList.size(); i++) {
                    bitmapList.get(i).recycle();
                }
                //返回此列表中指定的fromIndex（包含）和toIndex（独占）之间部分的视图。（
                bitmapList = bitmapList.subList(0, currentIndex + 1);
                isUndo = false;
            }

            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), null, true);
            bitmapList.add(bitmap);
            // 通过集合大小很容易判断出当前位置
            currentIndex = bitmapList.size() - 1;

            if (bitmapList.size() > CAPACITY) {
                //将最开始的一个释放掉，其后的往前移。
                bitmapList.get(1).recycle();
                //删除第一笔（0的位置有空的占位图）
                bitmapList.remove(1);
            }
        } catch (Exception e) {
        } catch (OutOfMemoryError e) {
        }

    }

    /**
     * @description:  判断当前是否第一步
     * @Param: []
     * @Return: boolean
     */
    public boolean currentIsFirst() {

        //是第一步的话，那么 bitmapList不为空，且当前位置为 -1+1 =0
        if (bitmapList != null && currentIndex == 0) {
            return true;
        }
        return false;
    }

    /**
     * @description:  判断当前是否最后一步
     * @Param: []
     * @Return: boolean
     */
    public boolean currentIsLast() {

        // 如果是最后一步，那么bitmapList不为空，且当前位置为总数减一。注意，这里的最后一步并不是当这个List满了的最后一步，而是现有的最后一个bitmap
        if (bitmapList != null && currentIndex == bitmapList.size() - 1) {
            return true;
        }
        return false;
    }

    /**
     * @description:  撤销操作的方法
     * @Param: [android.graphics.Bitmap]
     * @Return: void
     */
    public void undo(Bitmap srcBitmap) {

        if (bitmapList == null) {
            return;
        }
        isUndo = true;
        currentIndex--;
        if (currentIndex < 0) {
            currentIndex = 0;
        }
        try {
            Bitmap bitmap = bitmapList.get(currentIndex);
            if (bitmap.isRecycled()) {
                return;
            }
            //zoomImg:根据宽度缩放图片，高度等比例
            bitmap = BitmapUtil.zoomImg(bitmap, srcBitmap.getWidth());
            if (bitmap.getWidth() > srcBitmap.getWidth() || bitmap.getHeight() > srcBitmap.getHeight()) {
                bitmap = BitmapUtil.zoomImage(bitmap, srcBitmap.getWidth(), srcBitmap.getHeight());
            }
            //保存所有的像素的数组，图片宽×高
            int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];

            bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
            srcBitmap.setPixels(pixels, 0, bitmap.getWidth(), 0, 0,bitmap.getWidth(), bitmap.getHeight());
        } catch (OutOfMemoryError e) {
        }
    }

    /**
     * @description:  恢复（重做redo）操作
     * @Param: [android.graphics.Bitmap]
     * @Return: void
     */
    public void redo(Bitmap srcBitmap) {

        if (bitmapList == null) {
            return;
        }

        currentIndex++;
        int lastIndex = bitmapList.size() - 1;
        if (currentIndex >= lastIndex) {
            currentIndex = lastIndex;
        }
        try {
            Bitmap bitmap = bitmapList.get(currentIndex);
            if (bitmap.isRecycled()) {
                return;
            }
            bitmap = BitmapUtil.zoomImg(bitmap, srcBitmap.getWidth());
            if (bitmap.getWidth() > srcBitmap.getWidth() || bitmap.getHeight() > srcBitmap.getHeight()) {
                bitmap = BitmapUtil.zoomImage(bitmap, srcBitmap.getWidth(), srcBitmap.getHeight());
            }
            //保存所有的像素的数组，图片宽×高
            int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
            bitmap.getPixels(pixels, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
            srcBitmap.setPixels(pixels, 0, bitmap.getWidth(), 0, 0,bitmap.getWidth(), bitmap.getHeight());
        } catch (OutOfMemoryError e) {
        }

    }

    /**
     * @description:  清空这个回退队列
     * @Param: []
     * @Return: void
     */
    public void freeBitmaps() {

        if (bitmapList == null) {
            return;
        }
        for (Bitmap bitmap : bitmapList) {
            bitmap.recycle();
        }
        bitmapList.clear();
        bitmapList = null;
        currentIndex = -1;
    }

}
